package tbdp.tool.core.main;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Date;
import java.util.List;

import tbdp.tool.config.JobConfig;
import tbdp.tool.config.ProcessorConfig;
import tbdp.tool.config.ReaderConfig;
import tbdp.tool.config.WriterConfig;
import tbdp.tool.config.loader.ConfigLoadUtil;
import tbdp.tool.container.ProcessorContainer;
import tbdp.tool.container.ReaderContainer;
import tbdp.tool.container.WriterContainer;
import tbdp.tool.context.JobContext;
import tbdp.tool.core.loader.ServiceLoaderUtil;
import tbdp.tool.spi.Processor;
import tbdp.tool.spi.Reader;
import tbdp.tool.spi.RecordIterator;
import tbdp.tool.spi.Writer;
import tbdp.tool.util.DateFormatUtil;
import tbdp.tool.util.VariableContext;

/**
 * @author xbkaishui
 * @version $Id: Main.java, v 0.1 2017-06-17 下午4:18 xbkaishui Exp $$
 */
public class Main {

    private static final Logger logger = LoggerFactory.getLogger(Main.class);

    /**
     * 数据导出入口
     * 参数列表
     */
    public static void main(String[] args) {
        CommandLineParser parser = new CommandLineParser();
        RunConfig runConfig = parser.parse(args);
        runExport(runConfig);
    }

    public static void runExport(RunConfig config) {
        logger.info("runconfig {} ", config);
        prepareVarContext(config);
        init();
        runJob(config);
    }

    public static void init() {
        logger.info("init process reader ");
        ServiceLoaderUtil.loadProcess();
        ServiceLoaderUtil.loadReader();
        ServiceLoaderUtil.loadWriter();
    }

    public static void runJob(RunConfig config) {
        logger.info("start to run job");
        JobConfig jobConfig = ConfigLoadUtil.loadConfig(config.getDataType());
        JobContext jobContext = new JobContext();
        jobContext.setJobConfig(jobConfig);
        logger.info("start to run preProcessors  {} ", jobConfig.getPreProcessors());
        runProcessor(jobConfig.getPreProcessors(), jobContext);
        logger.info("start to run reader");
        RecordIterator recordIterator = runReader(jobContext);
        logger.info("start to run writer");
        runWriter(jobContext, recordIterator);
        logger.info("start to run preProcessors  {} ", jobConfig.getPostProcessors());
        runProcessor(jobConfig.getPostProcessors(), jobContext);

    }

    public static void runWriter(JobContext jobContext, RecordIterator recordIterator) {
        WriterConfig writerConfig = jobContext.getJobConfig().getWriter();
        Writer writer = WriterContainer.getWriter(writerConfig.getType());
        writer.write(jobContext, recordIterator);
        writer.postWriter(jobContext, recordIterator);
        writer.close(jobContext);
    }

    public static RecordIterator runReader(JobContext jobContext) {
        ReaderConfig readerConfig = jobContext.getJobConfig().getReader();
        Reader reader = ReaderContainer.getReader(readerConfig.getType());
        return reader.read(jobContext);
    }

    public static void runProcessor(List<ProcessorConfig> processors, JobContext jobContext) {
        for (ProcessorConfig processorConfig : processors) {
            Processor processor = ProcessorContainer.getProcessor(processorConfig.getType());
            if (processor.needHandle(jobContext.getJobConfig())) {
                processor.process(jobContext, processorConfig);
            }
        }
    }

    public static void prepareVarContext(RunConfig config) {
        VariableContext ctx = VariableContext.instance();
        String dateStr = config.getDate();
        Date date = DateFormatUtil.string2Date(dateStr, DateFormatUtil.TIME_FORMAT_D);
        ctx.addVariable("yyyymm", dateStr.substring(0, 6));
        ctx.addVariable("mm", dateStr.substring(6, dateStr.length()));
        ctx.addVariable("yyyy", dateStr.substring(0, 4));
        ctx.addVariable("date", dateStr);
        logger.info("variable ctx {} ", ctx.getCtx());
    }
}
